#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'James Iter'
__date__ = '16/1/7'
__contact__ = 'james.iter.cn@gmail.com'
__copyright__ = '(c) 2015 by James Iter.'


import sys, signal
import zmq
import json
import traceback
import thread
import jimit as ji

from models.initialize import logger, Init, objects_model, app
from models import RecodeOperate, Utils


if __name__ == '__main__':
    Init.init_db_conn()
    Init.init_cold_db_conn()
    Init.init_object_db_map()
    Init.init_objects_model()
    thread.start_new_thread(Init.db_keepalived, ())
    exit_flag = False


    def signal_handle(signum=0, frame=None):
        global exit_flag
        exit_flag = True

    signal.signal(signal.SIGTERM, signal_handle)

    context = zmq.Context.instance()
    socket = context.socket(zmq.REP)
    socket.connect('tcp://127.0.0.1:' + str(app.config['ZMQ_PORT'] + 1))

    args_rules = [
        (basestring, 'action', ['GET', 'POST', 'DELETE', 'PATCH', 'RPC']),
        (basestring, 'object_name', objects_model['index'].keys()),
        (dict, 'params')
    ]

    args_rules_by_get_with_params = [
        (basestring, 'filter_str')
    ]

    args_rules_by_delete_and_patch_with_params = [
        ((int, long), 'id')
    ]

    args_rules_by_rpc_with_params = [
        (basestring, 'function', ['generate_id_by', 'get_id_of_max_by'])
    ]

    while True:
        if exit_flag:
            sys.exit()

        ret = dict()
        ret['state'] = ji.Common.exchange_state(20000)

        try:
            message = socket.recv_json()

            ji.Check.previewing(args_rules, message)

            action = message['action']
            object_name = message['object_name']
            params = message['params']

            oo = RecodeOperate()
            oo.name = object_name

            if action == 'RPC':

                ji.Check.previewing(args_rules_by_rpc_with_params, params)
                function = params['function']
                if function == 'generate_id_by':
                    ret['id'] = Utils.generate_id_by(type_=object_name)
                elif function == 'get_id_of_max_by':
                    ret['id'] = Utils.get_id_of_max_by(type_=object_name)
                else:
                    logger.warning(''.join(['unknown action in ', json.dumps(message)]))
                    ret['state'] = ji.Common.exchange_state(50000)

            elif action == 'GET':

                ji.Check.previewing(args_rules_by_get_with_params, params)
                oo.filter_str = params['filter_str']
                ret['list'] = oo.get()

            elif action == 'POST':

                oo.kv = params
                oo.create()

            elif action == 'PATCH':

                ji.Check.previewing(args_rules_by_delete_and_patch_with_params, params)
                oo.kv = params
                oo.update()

            elif action == 'DELETE':

                ji.Check.previewing(args_rules_by_delete_and_patch_with_params, params)
                oo.kv = params
                oo.delete()

            else:
                logger.warning(''.join(['unknown action in ', json.dumps(message)]))
                ret['state'] = ji.Common.exchange_state(50000)

        except ji.JITError, e:
            logger.error(e.message)
            logger.error(traceback.format_exc())
            ret = json.loads(e.message)

        except Exception, e:
            logger.critical(e.message)
            logger.critical(traceback.format_exc())
            ret['state'] = ji.Common.exchange_state(50000)
            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', e.message])

        socket.send_json(ret)
